package huorong

import (
	"bytes"
	"encoding/json"
	"fmt"
	"go.uber.org/zap"
	"io"
	"io/ioutil"
	"net/http"
	"virus-proxy/internal/logger"
	"virus-proxy/internal/utils"
)

type HuorongScanner struct {
	ControlCenterIP   string
	ControlCenterPort string
	SecretID          string
	SecretKey         string
}

func (h *HuorongScanner) makeRequest(method, path string, body []byte) (*http.Response, error) {
	authHeader, err := generateAuthHeader(h.SecretID, h.SecretKey, method, path, body, nil)
	if err != nil {
		return nil, fmt.Errorf("Error generating auth header: %w", err)
	}

	req, _ := http.NewRequest(method, h.ControlCenterIP+":"+h.ControlCenterPort+path, bytes.NewBuffer(body))
	req.Header.Set("Authorization", authHeader)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("Error making request: %w", err)
	}
	return resp, nil
}

func (h *HuorongScanner) logResponse(resp *http.Response, action string) {
	bodyBytes, _ := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()
	logger.LogInfo(action, zap.String("response", string(bodyBytes)))
}

func (h *HuorongScanner) sendRequest(method, path string, body map[string]string) error {
	bodyBytes, err := json.Marshal(body)
	if err != nil && body != nil {
		return fmt.Errorf("Error mashaling body: %w", err)
	}
	resp, err := h.makeRequest(method, path, bodyBytes)
	if err != nil {
		return fmt.Errorf("Error making request: %w", err)
	}
	defer resp.Body.Close()
	h.logResponse(resp, "send Request")
	return nil
}

func (h *HuorongScanner) QueryAllGroups() (string, error) {
	// get方法获取全部分组
	resp, err := h.makeRequest("POST" /*h.ControlCenterIP+":"+h.ControlCenterPort+*/, "/api/group/_list", nil)
	if err != nil {
		logger.LogError(err.Error())
		return "", err
	}
	//defer resp.Body.Close()
	h.logResponse(resp, "Query All Groups")
	body, _ := ioutil.ReadAll(resp.Body)
	return string(body), nil
}

func (h *HuorongScanner) CreateGroup(groupName string) error {
	return h.sendRequest("POST", "/api/group", map[string]string{"group_name": groupName})
}

func (h *HuorongScanner) ModifyGroupName(groupID, newGroupName string) error {
	return h.sendRequest("PUT", fmt.Sprintf("/api/group/%s", groupID), map[string]string{"group_name": newGroupName})
}

func (h *HuorongScanner) DeleteGroup(groupID string) error {
	return h.sendRequest("DELETE", fmt.Sprintf("/api/group/%s", groupID), nil)
}

func (h *HuorongScanner) QueryTerminals() error {
	resp, err := h.makeRequest("GET", "/api/terminals", nil)
	if err != nil {
		logger.LogError(err.Error())
		return err
	}
	defer resp.Body.Close()
	h.logResponse(resp, "Query Terminals")
	return nil
}

func (h *HuorongScanner) QueryTerminalDetails(limit, offset int) ([]byte, error) {
	params := map[string]int{
		"limit":  limit,
		"offset": offset,
	}
	bodyBytes, _ := json.Marshal(params)
	resp, err := h.makeRequest("POST", "/api/clnts/_list", bodyBytes)
	if err != nil {
		logger.LogError(err.Error())
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		logger.LogError(err.Error())
		return nil, err
	}
	return body, nil
}

// 采用火绒的custom_scan接口
func (h *HuorongScanner) CallKillTask(scanList []string, clientIp string) ([]byte, error) {
	//newScanList := utils.ConvertToScanList(scanList, clientIp)
	newScanList := utils.ConvertToHuorong(scanList, clientIp)
	if newScanList == nil {
		return nil, fmt.Errorf("no such file or directory")
	}

	clientId, err := QueryClientId(h)
	if err != nil {
		return nil, err
	}

	var scanTask struct {
		Type  string `json:"type"`
		Param struct {
			WhitelistIgnore bool     `json:"whitelist_ignore"`
			ScanMaxSpeed    bool     `json:"scan_maxspeed"`
			CleanAutomate   bool     `json:"clean_automate"`
			CleanQuarantine bool     `json:"clean_quarantine"`
			ScanEndHalt     bool     `json:"scan_end_halt"`
			CannotCancel    bool     `json:"cannot_cancel"`
			ScanList        []string `json:"scan_list"`
		} `json:"param"`
		Clients []string `json:"clients"`
	}
	scanTask.Type = "custom_scan"
	scanTask.Param.WhitelistIgnore = true
	scanTask.Param.ScanMaxSpeed = false
	scanTask.Param.ScanEndHalt = false
	scanTask.Param.CleanQuarantine = true
	scanTask.Param.CleanAutomate = true
	scanTask.Param.CannotCancel = true
	scanTask.Param.ScanList = newScanList
	scanTask.Clients = []string{clientId}

	bodyBytes, _ := json.Marshal(scanTask)
	resp, err := h.makeRequest("POST", "/api/task/_create", bodyBytes)
	if err != nil {
		logger.LogError(err.Error())
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		logger.LogError(err.Error())
		return nil, err
	}
	return body, nil
}

func QueryClientId(h *HuorongScanner) (clientId string, err error) {
	body, err := h.QueryTerminalDetails(1, 0)
	if err != nil {
		logger.LogError(err.Error())
		return "", fmt.Errorf("error querying terminal details: %v", err)
	}

	var result struct {
		Errno int `json:"errno"`
		Data  struct {
			List []struct {
				ClientID string `json:"client_id"`
			} `json:"list"`
			Total int `json:"total"`
		} `json:"data"`
		ErrMsg string `json:"errmsg"`
	}

	err = json.Unmarshal(body, &result)
	if err != nil {
		logger.LogError(err.Error())
		return "", fmt.Errorf("error parsing response: %v", err)
	}

	if len(result.Data.List) > 0 {
		return result.Data.List[0].ClientID, nil
	} else {
		return "", fmt.Errorf(fmt.Sprintf("errno:%d,errmsg:%s", result.Errno, result.ErrMsg))
	}
}
